package xdu.lz.stage3_classloader.chapter2_classloader;

import java.io.*;

public class MyClassLoader extends ClassLoader {

    private static final String DEFAULT_DIR
            = "F:\\IDEA\\IDEA\\workspace\\multi-threaded-concurrency\\myclassloader1";

    private String dir = DEFAULT_DIR;

    private String classLoaderName;

    public MyClassLoader() {

    }

    public MyClassLoader(String classLoaderName) {
        this.classLoaderName = classLoaderName;
    }

    public String getDir() {
        return dir;
    }

    public void setDir(String dir) {
        this.dir = dir;
    }

    //指定加载器的父加载器
    public MyClassLoader(String classLoaderName, ClassLoader parent) {

        super(parent);
        this.classLoaderName = classLoaderName;
    }

    public String getClassLoaderName() {
        return classLoaderName;
    }

    /**
     * @param name package1.package2.AAA  ---> package1/package2/AAA.class
     * @return
     * @throws ClassNotFoundException
     */
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String classPath = name.replace(".", "/");

        File classFile = new File(dir, classPath + ".class");

        if (!classFile.exists()) {
            throw new ClassNotFoundException("The class [" + name + "] not find under+ ["+dir+" ]");
        }
        byte[] classBytes = loadClassBytes(classFile);
        if(classBytes == null){
            throw new ClassNotFoundException("load the class [" + name + "] failed");
        }
        return this.defineClass(name, classBytes, 0, classBytes.length);
    }

    private byte[] loadClassBytes(File classFile) {
        try (ByteArrayOutputStream out = new ByteArrayOutputStream();
             FileInputStream in = new FileInputStream(classFile)
        ) {
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = in.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            out.flush();
            return out.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

    }
}
